package com.aplikata.ui.oa;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;

import org.primefaces.event.CloseEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.UnselectEvent;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

import com.aplikata.bo.AplikataEmail;
import com.aplikata.bo.Domain;
import com.aplikata.bo.Msg;
import com.aplikata.bo.MsgInbox;
import com.aplikata.bo.MsgThread;
import com.aplikata.bo.User;
import com.aplikata.bo.UserReference;
import com.aplikata.constants.Constants;
import com.aplikata.evok.constants.EvokConstants;
import com.aplikata.service.MessagesService;
import com.aplikata.ui.UIBean;
import com.aplikata.util.AplikataEmailUtil;
import com.aplikata.util.FacesUtil;
import com.aplikata.util.StringUtil;

@ManagedBean(name = "messagesBean")
@ViewScoped
public class OAMessagesBean extends UIBean {

	private static final long serialVersionUID = 1L;
	@ManagedProperty(value = "#{messagesService}")
	private MessagesService messagesService;

	private MsgThread thread;
	private Msg msg;

	private MsgThread replyThread;
	private Msg replyMsg;

	private LazyDataModel<MsgInbox> msgLazyModel;

	private String schoolName;
	private Domain domain;
	private List<User> selectedUsers;

	private MsgInbox msgInbox;
	protected int pageSize = 15;

	private List<SelectItem> isReadSelectList;

	public OAMessagesBean() {
	}

	public LazyDataModel<MsgInbox> getMsgLazyModel() {
		if (msgLazyModel == null) {
			msgLazyModel = new LazyDataModel<MsgInbox>() {

				private static final long serialVersionUID = 1L;

				@Override
				public Object getRowKey(MsgInbox msg) {
					return msg.getId();
				}

				@Override
				public MsgInbox getRowData(String rowKey) {
					return (MsgInbox) messagesService.get(MsgInbox.class, Long.parseLong(rowKey));
				}

				@Override
				public void setRowIndex(int rowIndex) {
					if (rowIndex == -1 || getPageSize() == 0) {
						super.setRowIndex(-1);
					} else
						super.setRowIndex(rowIndex % getPageSize());
				}

				@SuppressWarnings({ "unchecked", "rawtypes" })
				@Override
				public List<MsgInbox> load(int first, int pageSize, String sortField, SortOrder sortOrder,
						Map<String, String> filters) {
					Object[] obj = messagesService.getUserMessages(first, pageSize, sortField, sortOrder, filters);
					msgLazyModel.setRowCount((Integer) obj[0]);
					return (List) obj[1];
				}
			};
		}

		return msgLazyModel;
	}

	@SuppressWarnings("unchecked")
	public List<String> completeUser(String name) {
		String[] names = name.split(" ");
		if (names == null || names.length == 0)
			return new ArrayList<String>();
		
		String sql = "SELECT {u.*}"
				   + " FROM _user u join _user_reference uf on u.id = uf.user_id";
		if (FacesUtil.getUserFromSession().getDomain() != null){
			sql += " left join evk_patient p on u.id = p.user_id" +
				   " left join evk_domain_patient dp on p.id = dp.patient_id " +
				   " where (dp.domain_id = " + FacesUtil.getUserFromSession().getDomain().getId() + 
				   " or u.domain_id = " + FacesUtil.getUserFromSession().getDomain().getId() + ")";
		}else if(FacesUtil.getUserFromSession().getRole().getName().equals(EvokConstants.ROLE_PATIENT)){			
			
			sql += " join evk_patient_therapy t on u.id = t.creator" +
				   " join evk_domain_patient dp on dp.id = t.domain_patient_id" +
			       " join evk_patient p on p.id = dp.patient_id" +
			       " join _user up on up.id = p.user_id and up.id = " + FacesUtil.getUserFromSession().getId();
		}
		
		if (names.length > 1) {
			sql += " and (uf.ime LIKE '%" + names[0] + "%' or uf.surname LIKE '%" + names[0]
					+ "%')";
			sql += " and (uf.ime LIKE '%" + names[1] + "%' or uf.surname LIKE '%" + names[1]
					+ "%')";
		} else {
			sql += " and (uf.ime LIKE '%" + names[0] + "%'";
			sql += " or uf.surname LIKE '%" + names[0] + "%')";
		}
		
		sql += " and u.id != " + FacesUtil.getUserFromSession().getId();
		

		sql += " group by u.id order by uf.ime, uf.surname";
		
		List list = messagesService.getSqlQuery(sql).addEntity("u", User.class).list();
		
		return list;
	}

	public void deleteAction(ActionEvent event) {
		if (msgInbox == null)
			return;

		try {
			messagesService.deleteMsgInbox(msgInbox);
			resetAll();
			FacesUtil.addInfoMessage("msg_delete_success");
		} catch (Exception e) {
			FacesUtil.addActionListenerException(e, log);
		}
	}

	public void addAction(ActionEvent event) {
		selectedUsers = null;
		thread = new MsgThread(FacesUtil.getUserFromSession());
		msg = new Msg(FacesUtil.getUserFromSession());
	}

	public void submitAction(ActionEvent event) {
		try {
			if (thread.getId() == null && selectedUsers.isEmpty() && getQyIsAllowFlag()) {
				FacesUtil.addErrorMessage("msg_users_empty");
				return;
			}
			Set<User> users = new HashSet<User>(selectedUsers);
			thread = messagesService.submitThread(thread, msg, users);

			// send email
			List<String> emaillist = new ArrayList<String>();
			Locale locale = null;
			for (User user : users) {
				UserReference uf = user.getUserReference();
				boolean sendemail = true;
				if(uf != null){
					sendemail =	uf.getSendEmail() == null ? true : uf.getSendEmail().booleanValue();
				}
				if (!StringUtil.isStrEmpty(user.getEmail()) && sendemail) {
					locale = FacesUtil.getUserLocale(user);
					emaillist.add(user.getEmail());
				}
			}

			if (!emaillist.isEmpty()) {
				String contentString = FacesUtil.getEmailMessage(
						Constants.EMAIL_NEW_MESSAGE_CONTENT,
						new Object[] {
								FacesUtil.getUserFromSession().getUserReference().getSurname() + " "
										+ FacesUtil.getUserFromSession().getUserReference().getName(),
								thread.getTitle(), msg.getContent(),
								AplikataEmailUtil.getAppLink() }, locale);

				AplikataEmail aemail = AplikataEmailUtil.prepareAplikataEmail(
						FacesUtil.getEmailMessage(Constants.EMAIL_NEW_MESSAGE_SUBJECT, new Object[]{AplikataEmailUtil.getAppName()}, locale), contentString,
						emaillist);

				try {
					aemail.getEmail().send();
				} catch (Exception e) {
					log.error("send message email failed!", e);
					try {
						messagesService.merge(aemail);
					} catch (Exception e1) {
						log.error("save message email failed!", e1);
					}
				}
			}
			resetAll();
			FacesUtil.addInfoMessage("msg_add_success");
		} catch (Exception e) {
			FacesUtil.addActionException(e, log);
		}
	}

	public void submitReplyAction(ActionEvent event) {
		try {
			replyThread = messagesService.submitMessage(replyThread, replyMsg);
			// send email
			User user = replyThread.getUser();
			UserReference uf = user.getUserReference();
			boolean sendemail = true;
			if(uf != null){
				sendemail = uf.getSendEmail() == null ? true : uf.getSendEmail().booleanValue();
			}
			if (!StringUtil.isStrEmpty(user.getEmail()) && sendemail) {
				AplikataEmail aemail = null;
				try {
					List<String> emaillist = new ArrayList<String>();
					emaillist.add(user.getEmail());
					Locale locale = FacesUtil.getUserLocale(user);

					String contentString = FacesUtil.getEmailMessage(
							Constants.EMAIL_NEW_MESSAGE_CONTENT,
							new Object[] {
									FacesUtil.getUserFromSession().getUserReference().getSurname() + " "
											+ FacesUtil.getUserFromSession().getUserReference().getName(),
									replyThread.getTitle(), replyMsg.getContent(),
									AplikataEmailUtil.getAppLink() }, locale);

					aemail = AplikataEmailUtil.prepareAplikataEmail(
							FacesUtil.getEmailMessage(Constants.EMAIL_NEW_MESSAGE_SUBJECT, new Object[]{AplikataEmailUtil.getAppName()}, locale), contentString,
							emaillist);

					aemail.getEmail().send();
				} catch (Exception e) {
					log.error("send message email failed!", e);
					try {
						messagesService.merge(aemail);
					} catch (Exception e1) {
						log.error("save message email failed!", e1);
					}
				}
			}

			msgInbox = null;
			msgLazyModel = null;
			replyMsg = new Msg(FacesUtil.getUserFromSession());
			FacesUtil.addInfoMessage("msg_update_success");
		} catch (Exception e) {
			FacesUtil.addActionException(e, log);
		}
	}

	public void resetAll() {
		msgInbox = null;
		thread = new MsgThread(FacesUtil.getUserFromSession());
		msg = new Msg(FacesUtil.getUserFromSession());
		msgLazyModel = null;
	}

	public void resetThread(CloseEvent event) {
		resetAll();
	}

	public String detailsAction() {
		if (msgInbox != null && msgInbox.isMsgRead()) {
			((MsgInbox) msgLazyModel.getRowData()).setMsgRead(false);
			messagesService.updateReadInboxMsg(msgInbox, false);
		}
		return null;
	}

	public void rowSelect(SelectEvent event) {
		msgInbox = (MsgInbox) event.getObject();
		if (msgInbox.isMsgRead()) {
			((MsgInbox) msgLazyModel.getRowData()).setMsgRead(false);
			messagesService.updateReadInboxMsg(msgInbox, false);
		}
	}

	public void expandAction(ActionEvent event) {
		System.out.println("tato je car");
	}

	public void rowUnSelect(UnselectEvent event) {
		msgInbox = null;
	}

	public MessagesService getMessagesService() {
		return messagesService;
	}

	public void setMessagesService(MessagesService messagesService) {
		this.messagesService = messagesService;
	}

	public MsgThread getThread() {
		if (thread == null)
			thread = new MsgThread(FacesUtil.getUserFromSession());
		return thread;
	}

	public void setThread(MsgThread thread) {
		this.thread = thread;
	}

	public Msg getMsg() {
		if (msg == null)
			msg = new Msg(FacesUtil.getUserFromSession());
		return msg;
	}

	public void setMsg(Msg msg) {
		this.msg = msg;
	}

	public MsgThread getReplyThread() {
		if (replyThread == null)
			replyThread = new MsgThread(FacesUtil.getUserFromSession());
		return replyThread;
	}

	public void setReplyThread(MsgThread replyThread) {
		this.replyThread = replyThread;
	}

	public Msg getReplyMsg() {
		if (replyMsg == null)
			replyMsg = new Msg(FacesUtil.getUserFromSession());
		return replyMsg;
	}

	public void setReplyMsg(Msg replyMsg) {
		this.replyMsg = replyMsg;
	}

	public String getSchoolName() {
		return schoolName;
	}

	public void setSchoolName(String schoolName) {
		this.schoolName = schoolName;
	}

	public Domain getDomain() {
		return domain;
	}

	public void setDomain(Domain domain) {
		this.domain = domain;
	}

	public List<User> getSelectedUsers() {
		return selectedUsers;
	}

	public void setSelectedUsers(List<User> selectedUsers) {
		this.selectedUsers = selectedUsers;
	}

	public MsgInbox getMsgInbox() {
		return msgInbox;
	}

	public void setMsgInbox(MsgInbox msgInbox) {
		this.msgInbox = msgInbox;
	}

	public Boolean getQyEditFlag() {
		if (thread != null && thread.getId() != null)
			return true;
		return false;
	}

	public Boolean getQyIsAllowFlag() {
		return true;
	}

	public List<SelectItem> getIsReadSelectList() {
		isReadSelectList = new ArrayList<SelectItem>();
		isReadSelectList.add(new SelectItem("", FacesUtil.getMessage("msg_all")));
		isReadSelectList.add(new SelectItem("0", FacesUtil.getMessage("msg_read")));
		isReadSelectList.add(new SelectItem("1", FacesUtil.getMessage("msg_unread")));
		return isReadSelectList;
	}

	public void setIsReadSelectList(List<SelectItem> isReadSelectList) {
		this.isReadSelectList = isReadSelectList;
	}

	public Long getMsgCounter() {
		return (Long) messagesService.findSingleByNamedQuery("msgInbox.countUserMsg", new Object[] { FacesUtil
				.getUserFromSession().getId() });
	}
}
